package com.lzh.crypt.util;

import com.lzh.crypt.ase.AESAdvancedKeyPair;
import com.lzh.crypt.ase.AESKeyPair;
import com.lzh.crypt.enums.AesAlgorithmEnum;
import com.lzh.crypt.exception.AESException;
import com.lzh.crypt.exception.ErrorCode;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;

/**
 * @author zhehen.lu
 * @date 2025/8/10 19:56
 */
public class AESUtils {

    public static String genericKey() {
        return genericKey(128);
    }

    public static String genericKey(int size) {
        try {
            return Base64.encodeBase64String(AESKeyPair.genericKey(size));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static byte[] encrypt(byte[] content, String key) {
        AESKeyPair aesKeyPair = AESKeyPair.instance(Base64.decodeBase64(key));
        try {
            return aesKeyPair.encrypt(content);
        } catch (Exception e) {
            throw new AESException(ErrorCode.ENCRYPTION_ERROR.getErrorMsg(), e);
        }
    }

    public static byte[] decrypt(byte[] secContent, String key) {
        AESKeyPair aesKeyPair = AESKeyPair.instance(Base64.decodeBase64(key));
        try {
            return aesKeyPair.decrypt(secContent);
        } catch (Exception e) {
            throw new AESException(ErrorCode.DECRYPTION_ERROR.getErrorMsg(), e);
        }
    }

    public static byte[] encrypt(byte[] content, String key, AesAlgorithmEnum aesAlgorithmEnum) {
        AESKeyPair aesKeyPair = AESKeyPair.instance(Base64.decodeBase64(key), aesAlgorithmEnum);
        try {
            return aesKeyPair.encrypt(content);
        } catch (Exception e) {
            throw new AESException(ErrorCode.ENCRYPTION_ERROR.getErrorMsg(), e);
        }
    }

    public static byte[] decrypt(byte[] secContent, String key, AesAlgorithmEnum aesAlgorithmEnum) {
        AESKeyPair aesKeyPair = AESKeyPair.instance(Base64.decodeBase64(key), aesAlgorithmEnum);
        try {
            return aesKeyPair.decrypt(secContent);
        } catch (Exception e) {
            throw new AESException(ErrorCode.DECRYPTION_ERROR.getErrorMsg(), e);
        }
    }

    public static String encrypt2Base64(byte[] content, String key) {
        byte[] secContent = encrypt(content, key);
        return Base64.encodeBase64String(secContent);
    }

    public static String decrypt2Base64(byte[] secContent, String key) {
        byte[] content = decrypt(secContent, key);
        return new String(content, StandardCharsets.UTF_8);
    }

    public static String encrypt2Base64(byte[] content, String key, AesAlgorithmEnum cryptAlgorithm) {
        byte[] secContent = encrypt(content, key, cryptAlgorithm);
        return Base64.encodeBase64String(secContent);
    }

    public static String decrypt2Base64(byte[] secContent, String key, AesAlgorithmEnum cryptAlgorithm) {
        byte[] content = decrypt(secContent, key, cryptAlgorithm);
        return new String(content, StandardCharsets.UTF_8);
    }

    public static String encrypt2Base64(String content, String key) {
        return encrypt2Base64(content.getBytes(StandardCharsets.UTF_8), key);
    }

    public static String decrypt2Base64(String secContent, String key) {
        return decrypt2Base64(Base64.decodeBase64(secContent), key);
    }

    public static String encryptAES128CBCPKS72Base64(String content, String key, String iv) {
        return encrypt(AesAlgorithmEnum.AES_128_CBC_PKCS7, content, key, iv);
    }

    public static String decryptAES128CBCPKS72Str(String secContent, String key, String iv) {
        return decrypt(AesAlgorithmEnum.AES_128_CBC_PKCS7, secContent, key, iv);
    }

    public static String encrypt(AesAlgorithmEnum aesAlgorithmEnum, String content, String key, String iv) {
        AESAdvancedKeyPair advancedKeyPair = AESAdvancedKeyPair.instance(aesAlgorithmEnum, Base64.decodeBase64(key),
                Base64.decodeBase64(iv), Cipher.ENCRYPT_MODE);
        byte[] contentByte = content.getBytes(StandardCharsets.UTF_8);
        return Base64.encodeBase64String(advancedKeyPair.encrypt(contentByte));
    }

    public static String decrypt(AesAlgorithmEnum aesAlgorithmEnum, String secContent, String key, String iv) {
        AESAdvancedKeyPair advancedKeyPair = AESAdvancedKeyPair.instance(aesAlgorithmEnum, Base64.decodeBase64(key),
                Base64.decodeBase64(iv), Cipher.DECRYPT_MODE);
        byte[] contentByte = Base64.decodeBase64(secContent);
        return new String(advancedKeyPair.decrypt(contentByte), StandardCharsets.UTF_8);
    }

    public static String encrypt(AesAlgorithmEnum aesAlgorithmEnum, String content, String key, String iv,
                                 String additionAuthData) {
        AESAdvancedKeyPair advancedKeyPair = AESAdvancedKeyPair.instance(aesAlgorithmEnum, Base64.decodeBase64(key),
                Base64.decodeBase64(iv), Base64.decodeBase64(additionAuthData), Cipher.ENCRYPT_MODE);
        byte[] contentByte = content.getBytes(StandardCharsets.UTF_8);
        return Base64.encodeBase64String(advancedKeyPair.encrypt(contentByte));
    }

    public static String decrypt(AesAlgorithmEnum aesAlgorithmEnum, String secContent, String key, String iv,
                                 String additionAuthData) {
        AESAdvancedKeyPair advancedKeyPair = AESAdvancedKeyPair.instance(aesAlgorithmEnum, Base64.decodeBase64(key),
                Base64.decodeBase64(iv), Base64.decodeBase64(additionAuthData), Cipher.DECRYPT_MODE);
        byte[] contentByte = Base64.decodeBase64(secContent);
        return new String(advancedKeyPair.decrypt(contentByte), StandardCharsets.UTF_8);
    }

    public static String encrypt(AesAlgorithmEnum aesAlgorithmEnum, byte[] content, byte[] key, byte[] iv,
                                 byte[] additionAuthData) {
        AESAdvancedKeyPair advancedKeyPair = AESAdvancedKeyPair.instance(aesAlgorithmEnum, key, iv, additionAuthData,
                Cipher.ENCRYPT_MODE);
        return Base64.encodeBase64String(advancedKeyPair.encrypt(content));
    }

    public static String decrypt(AesAlgorithmEnum aesAlgorithmEnum, byte[] secContent, byte[] key, byte[] iv,
                                 byte[] additionAuthData) {
        AESAdvancedKeyPair advancedKeyPair = AESAdvancedKeyPair.instance(aesAlgorithmEnum, key, iv, additionAuthData,
                Cipher.DECRYPT_MODE);
        return new String(advancedKeyPair.decrypt(secContent), StandardCharsets.UTF_8);
    }

}
